import axios from 'axios'
import Qs from 'qs'
import MD5 from 'md5.js'

import {Message} from 'ant-design-vue'

const BASE_URL = process.env === 'production' ? process.env.VUE_APP_API_URL : '/v1';

let APP_SECRET = new MD5().update(process.env.VUE_APP_PARTNER_ID + process.env.VUE_APP_KEY).digest('hex')
if(process.env.VUE_APP_REQUEST_FROM === 'wechatApp'){
  APP_SECRET = process.env.VUE_APP_APP_SECRET
}

// 判断是否正在请求token, 默认不在请求
let is_refreshing = false
// 存储挂起的请求函数
let requests = []

// 创建axios
const service = axios.create({
  timeout: 10 * 1000,
  withCredentials: true,
  baseURL: BASE_URL,
  headers: {
    "Content-Type": "application/x-www-form-urlencoded;",
    "Accept": "application/json, text/javascript, */*; q=0.01",
  },
  transformRequest: [function(data) {
    data.partner_id = process.env.VUE_APP_PARTNER_ID
    return Qs.stringify(data)
  }],
})

// 请求拦截
service.interceptors.request.use(
  config => {
    config.future = true;
    config.form_params = {
      partner_id: process.env.VUE_APP_PARTNER_ID,
      is_from_app: 0,
      ...config.data
    }
    
    if(process.env.VUE_APP_REQUEST_FROM){
      config.headers.common.request_from = process.env.VUE_APP_REQUEST_FROM
    }
    
    // 判断是否需要获取token的请求
    if(config.data.skip_getting_token){
      return config
    }
    refreshToken(config);
    return config
  },
  error => {
    console.error('request error: ', error);
    Promise.reject(error);
  }
)

// 响应拦截
service.interceptors.response.use(
  res => {
    if(res.status === 200){
      const data = res.data
      if(data.code === 200){
        return Promise.resolve(data.data)
      }else {
        console.error('response err: ', res);
        if(res.data.code !== 301 && res.data.code !== 308){
          Message.error(res.data.reason)
          return Promise.reject(res.data.reason)
        }else {
          if(res.data.code === 301){
            // token失效，跳转登录？
            window.localStorage.removeItem('access_token')
            refreshToken(res.config)
          }else if (res.data.code === 308){
            // 登录超时
          }

        }
      }
    }else {
      console.warn('network error');
      return Promise.reject(new Error(res.data.message || 'network Error'))
    }
  },
  error => Promise.reject(error)
)

/**
 * 提取更新token的方法
 * @param {*} config 请求拦截的config
 */
function refreshToken(config) {
  // 校验token过期
  const exit_token = window.localStorage.access_token
  const exit_expired_at = window.localStorage.expired_at
  const now = String(new Date().getTime()).substr(0,10)

  if(!exit_token || exit_token === 'undefined' || Number(now) > Number(exit_expired_at)) {
    // 是否正在请求token
    if(!is_refreshing){
      is_refreshing = true
      getToken().then(res => {
        const {expired_at, access_token} = res
        // 因token的时效性，需要放在localstorage
        window.localStorage.setItem('access_token', access_token)
        window.localStorage.setItem('expired_at', expired_at)
        // 设置请求头
        config.headers.common['authorization'] = access_token

        is_refreshing = false
        return access_token
      }).then(access_token => {
        // 将缓存的请求序列依次放开
        requests.forEach(cb => cb(access_token))
        // 重置缓存的请求序列
        requests = []
      }).catch( res =>{
        console.error('refresh token error：', res);
        window.location.replace('/')
      }).finally( () => {
        is_refreshing = false
      })
    }
      // 缓存需要更新token但是正在进行的请求
      return new Promise( resolve => {
        requests.push( () => {
          resolve(config)
        })
      })
  }else{
    config.headers.common['authorization'] = exit_token
  }
}

/**
 * 获取token实例
 */
function getToken () {
  return service.post('/login/access_token', {
    skip_getting_token: true
  }, {
    headers: {
      "Authorization": 'Basic ' + Buffer.from(`${process.env.VUE_APP_PARTNER_ID}:${APP_SECRET}`).toString('base64')
    }
  })
}

export default service;